﻿/*
 * Copyright © 2020, Wuxi Safover Intelligent Technology Co., Ltd. All rights reserved.
 * 
 * 无锡安永智能科技有限公司版权所有，未经许可，不得用于商业用途
 * 
 * Visit: https://www.safover.com/ 
 */

using System;
using System.Threading;
using Safover.Lidar.DataContract;
using static Safover.LidarCollector.Managers.DeviceManager;

namespace Safover.LidarCollector.Managers
{
    internal class VerticalScan : SingleScan
    {
        protected override string Name => "VerticalScan";

        protected override LidarWorkMode LidarWorkMode => LidarWorkMode.Vertical;

        protected override LidarScanMode LidarScanMode => LidarScanMode.Vertical;

        internal VerticalScan(PeriodicScanParams periodicScanParams) : base(periodicScanParams)
        {
        }

        internal SingleScanResult Scan(VerticalScanControlLogic scanContolLogic, DataCacher cacher, SingleCollectionWorkingStatusChangedEventHandler handler)
        {
            Log.DebugWriteLine($"{Name}: Ready to start {LidarWorkMode} Scan.");

            VScanInstruction instruction = scanContolLogic.Tick();

            if (!instruction.CanScan) return SingleScanResult.PeriodicalScanFinished;

            var horizontalAngle = instruction.FixedHorizontalAngle;
            var verticalAngle = (float)instruction.ScanAngle;

            handler?.Invoke(new SingleCollectionWorkingStatusChangedEventArgs
            {
                IsSingleCollecting = true,
                SingleLidarWorkMode = LidarWorkMode,
                PercentageCompletion = .05f,
                Message = $"Moving Rotary Table to VAngle={verticalAngle}",
                CountDownSecondsForNextFixedCollection = 0
            });

            // Must do
            if (MoveRotaryTableVertically(verticalAngle))
            {
                Log.DebugWriteLine($"----- {Name}: Rotary Table is Ready for {LidarWorkMode} step scan, fixed horizontal angle = 【{horizontalAngle}】, vertical angle = 【{verticalAngle}】.");
            }

            if (instruction.ShouldMoveOpposite)
            {
                // 云台180度反转
                handler?.Invoke(new SingleCollectionWorkingStatusChangedEventArgs
                {
                    IsSingleCollecting = true,
                    SingleLidarWorkMode = LidarWorkMode,
                    PercentageCompletion = .1f,
                    Message = $"Moving Horizontally to {horizontalAngle}",
                });

                if (MoveRotaryTableHorizontally(horizontalAngle))
                {
                    Log.DebugWriteLine($"{Name}: Rotary table is moved to horizontal angle = [{horizontalAngle}].");
                }
            }

            handler?.Invoke(new SingleCollectionWorkingStatusChangedEventArgs
            {
                IsSingleCollecting = true,
                SingleLidarWorkMode = LidarWorkMode,
                PercentageCompletion = .15f,
                Message = "Rotary Table is Ready",
            });

            if (!DeviceFactoryInstance.OpticalMaserDevice.StartLasar())
            {
                throw new OpticalMaserMalfunctionException($"{Name}: Failed to start optical maser.");
            }

            Log.DebugWriteLine($"{Name}: Lasar is on.");

            handler?.Invoke(new SingleCollectionWorkingStatusChangedEventArgs
            {
                IsSingleCollecting = true,
                SingleLidarWorkMode = LidarWorkMode,
                Message = "Laser is on",
                PercentageCompletion = .25f
            });

            StartCatchingData(cacher, TimeSpan.FromSeconds(SingleAcquisitionTimeout));

            if (!DeviceFactoryInstance.OpticalMaserDevice.StopLasar())
            {
                throw new OpticalMaserMalfunctionException("Failed to stop optical maser.");
            }

            handler?.Invoke(new SingleCollectionWorkingStatusChangedEventArgs
            {
                IsSingleCollecting = false,
                SingleLidarWorkMode = LidarWorkMode,
                PercentageCompletion = .95f,
                Message = "Laser is off, Saving Data",
            });

            var startAngle = scanContolLogic.StartAngle;
            var endAngle = scanContolLogic.EndAngle;

            FinishSingleScan(cacher, startAngle, endAngle, horizontalAngle, verticalAngle/*, folderName*/);

            handler?.Invoke(new SingleCollectionWorkingStatusChangedEventArgs
            {
                IsSingleCollecting = false,
                SingleLidarWorkMode = LidarWorkMode,
                PercentageCompletion = 1f
            });

            Log.DebugWriteLine($"[Thread={Thread.CurrentThread.Name}]: {LidarWorkMode}, single collection done.");

            return SingleScanResult.Success;
        }

    }
}
